Conversation
WalkthroughThis pull request introduces AI-generated prompt functionality to the documentation site. It adds a banner component that displays and allows copying of AI prompts linked to guide pages, including schema support for prompt metadata, utilities for extracting prompt content, page integration logic, documentation guidelines, and an example Nuxt prompt implementation. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Tip Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
apps/docs/src/lib/get-prompt-content.ts (1)
15-18:promptPageUrlis computed but never consumed — either wire it up or drop it.
AIPromptBanneraccepts only{ fullPrompt, guideName }, andpage.tsxonly destructurespromptContent.fullPrompt. The URL for the full prompt page is silently discarded. This looks like a "View full prompt" link was planned but not implemented. Either add a link to the banner or remove the field to avoid misleading future maintainers.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/docs/src/lib/get-prompt-content.ts` around lines 15 - 18, The returned object from getPromptContent (returning fullPrompt and promptPageUrl) includes promptPageUrl but nothing consumes it; either remove promptPageUrl from the return value or thread it through and render a "View full prompt" link: update get-prompt-content.ts to stop returning promptPageUrl OR update AIPromptBanner props to accept promptPageUrl (in addition to fullPrompt and guideName) and update page.tsx where promptContent is used to pass promptContent.promptPageUrl into AIPromptBanner and render the link inside AIPromptBanner (use the existing fullPrompt/guideName props and add a conditional anchor/button that navigates to promptPageUrl). Ensure all references to promptPageUrl are removed if you choose to drop it to avoid dead data.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/docs/content/docs/ai/prompts/nuxt.mdx`:
- Around line 167-170: The VERSION REQUIREMENTS section currently states
"Node.js: 20.19 or higher (Node.js 18 is NOT supported)" which conflicts with
the other Nuxt guide line that says "Node.js 18+"; verify the actual Prisma v7
Node requirement and update the "## VERSION REQUIREMENTS" block (the "Node.js:
20.19 or higher (Node.js 18 is NOT supported)" bullet) and/or the other Nuxt
guide statement so both docs state the same, correct minimum Node version and
any explicit non‑support note.
- Around line 319-352: The test script's testDatabase function will fail on
rerun due to inserting a duplicate demo email and will leave the Node process
hanging because the Prisma client isn't disconnected; update testDatabase to
avoid uniqueness errors by using an upsert or find-or-create flow when calling
prisma.user.create (e.g., use prisma.user.upsert or check with
prisma.user.findUnique before create) and ensure the Prisma client is always
closed by calling prisma.$disconnect() in a finally block (or before
process.exit) so connections are cleaned up and the process exits cleanly.
In `@apps/docs/PROMPT_GUIDE.md`:
- Line 52: The MD040 false positive is caused by the nested fenced code block
(the outer closing fence using ````) in PROMPT_GUIDE.md; wrap the problematic
outer fence with an inline markdownlint suppression by inserting <!--
markdownlint-disable MD040 --> immediately before the outer fenced block (the
```` fence) and <!-- markdownlint-enable MD040 --> immediately after it so the
linter ignores the unlabeled outer fence while preserving the nested ```mdx /
```md content.
In `@apps/docs/src/components/ai-prompt-banner.tsx`:
- Around line 29-41: The button in the AiPromptBanner component currently relies
on the default HTML behavior (type="submit") which can inadvertently submit
ancestor forms; update the button element rendered in ai-prompt-banner (the
element using cn(...) and buttonVariants({...}) with onClick and checked) to
explicitly include type="button" to prevent accidental form submissions while
preserving the existing className, onClick handler, and checked conditional
content.
In `@apps/docs/src/lib/get-prompt-content.ts`:
- Around line 11-13: Wrap the await page.data.getText("processed") call and
subsequent processing in a try/catch so any thrown error returns null instead of
crashing the page; inside the try, read processed, use a CRLF-safe regex like
/````md\r?\n([\s\S]*?)\r?\n````/ to build match, return null if no match, and
otherwise return the object with fullPrompt: match[1] and promptPageUrl:
page.url; on catch simply return null. This change touches the processed and
match handling in get-prompt-content (the code that returns { fullPrompt,
promptPageUrl }).
---
Nitpick comments:
In `@apps/docs/src/lib/get-prompt-content.ts`:
- Around line 15-18: The returned object from getPromptContent (returning
fullPrompt and promptPageUrl) includes promptPageUrl but nothing consumes it;
either remove promptPageUrl from the return value or thread it through and
render a "View full prompt" link: update get-prompt-content.ts to stop returning
promptPageUrl OR update AIPromptBanner props to accept promptPageUrl (in
addition to fullPrompt and guideName) and update page.tsx where promptContent is
used to pass promptContent.promptPageUrl into AIPromptBanner and render the link
inside AIPromptBanner (use the existing fullPrompt/guideName props and add a
conditional anchor/button that navigates to promptPageUrl). Ensure all
references to promptPageUrl are removed if you choose to drop it to avoid dead
data.
| ## VERSION REQUIREMENTS | ||
|
|
||
| - **Node.js**: 20.19 or higher (Node.js 18 is NOT supported) | ||
| - **TypeScript**: 5.4.0 or higher (5.9.x recommended) |
There was a problem hiding this comment.
Node.js version requirement conflicts with the main Nuxt guide.
This prompt specifies Node.js 20.19+ (with an explicit "Node.js 18 is NOT supported"), but the companion guide (content/docs/guides/frameworks/nuxt.mdx, line 15) lists "Node.js 18+". A user who reads both will get contradictory signals. One of them needs to be updated to match the actual Prisma v7 requirement.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/docs/content/docs/ai/prompts/nuxt.mdx` around lines 167 - 170, The
VERSION REQUIREMENTS section currently states "Node.js: 20.19 or higher (Node.js
18 is NOT supported)" which conflicts with the other Nuxt guide line that says
"Node.js 18+"; verify the actual Prisma v7 Node requirement and update the "##
VERSION REQUIREMENTS" block (the "Node.js: 20.19 or higher (Node.js 18 is NOT
supported)" bullet) and/or the other Nuxt guide statement so both docs state the
same, correct minimum Node version and any explicit non‑support note.
| async function testDatabase() { | ||
| console.log("🔍 Testing Prisma Postgres connection...\n"); | ||
|
|
||
| try { | ||
| // Test 1: Check connection | ||
| console.log("✅ Connected to database!"); | ||
|
|
||
| // Test 2: Create a test user | ||
| console.log("\n📝 Creating a test user..."); | ||
| const newUser = await prisma.user.create({ | ||
| data: { | ||
| email: "demo@example.com", | ||
| name: "Demo User", | ||
| }, | ||
| }); | ||
| console.log("✅ Created user:", newUser); | ||
|
|
||
| // Test 3: Fetch all users | ||
| console.log("\n📋 Fetching all users..."); | ||
| const allUsers = await prisma.user.findMany(); | ||
| console.log(`✅ Found ${allUsers.length} user(s):`); | ||
| allUsers.forEach((user) => { | ||
| console.log(` - ${user.name} (${user.email})`); | ||
| }); | ||
|
|
||
| console.log("\n🎉 All tests passed! Your database is working perfectly.\n"); | ||
| } catch (error) { | ||
| console.error("❌ Error:", error); | ||
| process.exit(1); | ||
| } | ||
| } | ||
|
|
||
| testDatabase(); | ||
| ``` |
There was a problem hiding this comment.
The generated test script will fail on the second run and hang the process.
Two concrete problems with the scripts/test-database.ts example that the AI assistant will produce for users:
- Uniqueness violation on re-run:
prisma.user.create({ data: { email: "demo@example.com" } })will throw a unique constraint error the second timenpm run db:testis executed, making the test misleading as a connectivity check. - Process hangs: There is no
prisma.$disconnect()call, so the Node.js process won't exit cleanly and the terminal hangs until the PG connection pool times out.
🔧 Suggested fix for the test script example
async function testDatabase() {
console.log("🔍 Testing Prisma Postgres connection...\n");
try {
console.log("✅ Connected to database!");
console.log("\n📝 Creating a test user...");
- const newUser = await prisma.user.create({
- data: {
- email: "demo@example.com",
- name: "Demo User",
- },
+ const newUser = await prisma.user.upsert({
+ where: { email: "demo@example.com" },
+ update: {},
+ create: {
+ email: "demo@example.com",
+ name: "Demo User",
+ },
});
console.log("✅ Created user:", newUser);
console.log("\n📋 Fetching all users...");
const allUsers = await prisma.user.findMany();
console.log(`✅ Found ${allUsers.length} user(s):`);
allUsers.forEach((user) => {
console.log(` - ${user.name} (${user.email})`);
});
console.log("\n🎉 All tests passed! Your database is working perfectly.\n");
} catch (error) {
console.error("❌ Error:", error);
+ } finally {
+ await prisma.$disconnect();
}
}
-testDatabase();
+testDatabase().then(() => process.exit(0)).catch(() => process.exit(1));🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/docs/content/docs/ai/prompts/nuxt.mdx` around lines 319 - 352, The test
script's testDatabase function will fail on rerun due to inserting a duplicate
demo email and will leave the Node process hanging because the Prisma client
isn't disconnected; update testDatabase to avoid uniqueness errors by using an
upsert or find-or-create flow when calling prisma.user.create (e.g., use
prisma.user.upsert or check with prisma.user.findUnique before create) and
ensure the Prisma client is always closed by calling prisma.$disconnect() in a
finally block (or before process.exit) so connections are cleaned up and the
process exits cleanly.
| ````md | ||
| (your full prompt content here — see "Writing the prompt" below) | ||
| ```` | ||
| ```` |
There was a problem hiding this comment.
MD040 lint warning is a structural false positive — consider a lint-ignore directive.
The markdownlint-cli2 warning on line 52 ("Fenced code blocks should have a language specified") is triggered by the nested ````mdx / ````md structure: the linter loses track of nesting depth and interprets the outer closing fence as an unlabeled opening. The content is correct; the tool is simply confused.
If the project's markdownlint config supports it, an inline suppression avoids the noise without changing the document:
🔇 Optional: suppress the false-positive lint warning
+<!-- markdownlint-disable MD040 -->
````mdx
...+
</details>
<details>
<summary>🧰 Tools</summary>
<details>
<summary>🪛 markdownlint-cli2 (0.21.0)</summary>
[warning] 52-52: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
</details>
</details>
<details>
<summary>🤖 Prompt for AI Agents</summary>
Verify each finding against the current code and only fix it if needed.
In @apps/docs/PROMPT_GUIDE.md at line 52, The MD040 false positive is caused by
the nested fenced code block (the outer closing fence using ) in PROMPT_GUIDE.md; wrap the problematic outer fence with an inline markdownlint suppression by inserting <!-- markdownlint-disable MD040 --> immediately before the outer fenced block (the fence) and
immediately after it so the linter ignores the unlabeled outer fence while
preserving the nested mdx / md content.
</details>
<!-- fingerprinting:phantom:poseidon:churro -->
<!-- This is an auto-generated comment by CodeRabbit -->
| <button | ||
| className={cn( | ||
| buttonVariants({ | ||
| color: "primary", | ||
| size: "sm", | ||
| className: "gap-2 shrink-0", | ||
| }), | ||
| )} | ||
| onClick={onClick} | ||
| > | ||
| {checked ? <Check className="size-3.5" /> : <Copy className="size-3.5" />} | ||
| {checked ? "Copied!" : "Copy prompt"} | ||
| </button> |
There was a problem hiding this comment.
Add type="button" to prevent accidental form submissions.
HTML <button> defaults to type="submit", which would submit any ancestor <form>. Adding type="button" is cheap defensive coding and a consistent best practice for action buttons.
🛠️ Proposed fix
- <button
+ <button
+ type="button"
className={cn(📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <button | |
| className={cn( | |
| buttonVariants({ | |
| color: "primary", | |
| size: "sm", | |
| className: "gap-2 shrink-0", | |
| }), | |
| )} | |
| onClick={onClick} | |
| > | |
| {checked ? <Check className="size-3.5" /> : <Copy className="size-3.5" />} | |
| {checked ? "Copied!" : "Copy prompt"} | |
| </button> | |
| <button | |
| type="button" | |
| className={cn( | |
| buttonVariants({ | |
| color: "primary", | |
| size: "sm", | |
| className: "gap-2 shrink-0", | |
| }), | |
| )} | |
| onClick={onClick} | |
| > | |
| {checked ? <Check className="size-3.5" /> : <Copy className="size-3.5" />} | |
| {checked ? "Copied!" : "Copy prompt"} | |
| </button> |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/docs/src/components/ai-prompt-banner.tsx` around lines 29 - 41, The
button in the AiPromptBanner component currently relies on the default HTML
behavior (type="submit") which can inadvertently submit ancestor forms; update
the button element rendered in ai-prompt-banner (the element using cn(...) and
buttonVariants({...}) with onClick and checked) to explicitly include
type="button" to prevent accidental form submissions while preserving the
existing className, onClick handler, and checked conditional content.
| const processed = await page.data.getText("processed"); | ||
| const match = processed.match(/````md\n([\s\S]*?)\n````/); | ||
| if (!match) return null; |
There was a problem hiding this comment.
Wrap getText("processed") in a try/catch — an unhandled exception here hard-fails the docs page.
getText("processed") is an async call with no error boundary. If it throws for any reason (fumadocs API surface change, the includeProcessedMarkdown: true postprocess being absent, etc.), the exception propagates through the awaiting page.tsx and breaks page rendering for every guide that has aiPrompt in frontmatter. Since the banner is an enhancement, not core content, this should degrade gracefully.
The regex also uses literal \n, so a CRLF-terminated file will silently miss the match. Anchoring with \r?\n is a cheap safeguard.
🛡️ Proposed fix
export async function getPromptContent(slug: string) {
const page = source.getPage(["ai", "prompts", slug]);
if (!page) return null;
- const processed = await page.data.getText("processed");
- const match = processed.match(/````md\n([\s\S]*?)\n````/);
- if (!match) return null;
+ try {
+ const processed = await page.data.getText("processed");
+ const match = processed.match(/````md\r?\n([\s\S]*?)\r?\n````/);
+ if (!match) return null;
+
+ return {
+ fullPrompt: match[1],
+ promptPageUrl: page.url,
+ };
+ } catch {
+ return null;
+ }
-
- return {
- fullPrompt: match[1],
- promptPageUrl: page.url,
- };
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/docs/src/lib/get-prompt-content.ts` around lines 11 - 13, Wrap the await
page.data.getText("processed") call and subsequent processing in a try/catch so
any thrown error returns null instead of crashing the page; inside the try, read
processed, use a CRLF-safe regex like /````md\r?\n([\s\S]*?)\r?\n````/ to build
match, return null if no match, and otherwise return the object with fullPrompt:
match[1] and promptPageUrl: page.url; on catch simply return null. This change
touches the processed and match handling in get-prompt-content (the code that
returns { fullPrompt, promptPageUrl }).
Summary by CodeRabbit
New Features
Documentation